import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Query {
	private ArrayList<SingleQueryThread> queryList;
	private ArrayList<Thread> threadList;
	private double[] cenConf;

	public Query(String concept1, String concept2, int type) {
		this.queryList = new ArrayList<SingleQueryThread>();

		String c1 = Query.transformString(concept1);
		String c2 = Query.transformString(concept2);
		String cenConfFileName = "";
		String c1UrlFileName = "";
		String c2UrlFileName = "";

		// create the res directory it doesn't exist
		File resDir = new File("./res");
		if (!resDir.exists())
			resDir.mkdir();

		// configure which fight to do : color or emotion
		if (type == 1) {
			cenConfFileName = "./res/CenConf_" + c1 + "_" + c2 + "_emotion.txt";
			c1UrlFileName = "./res/" + c1 + "_emotion_img.txt";
			c2UrlFileName = "./res/" + c2 + "_emotion_img.txt";
			for (int i = 0; i < Vocabulary.EMOTIONS.length; i++) {
				queryList.add(new SingleQueryThread(c1 + ","
						+ Vocabulary.EMOTIONS[i], i % 3));
			}
			for (int i = 0; i < Vocabulary.EMOTIONS.length; i++) {
				queryList.add(new SingleQueryThread(c2 + ","
						+ Vocabulary.EMOTIONS[i], i % 3));
			}
		} else if (type == 2) {
			cenConfFileName = "./res/CenConf_" + c1 + "_" + c2 + "_color.txt";
			c1UrlFileName = "./res/" + c1 + "_color_img.txt";
			c2UrlFileName = "./res/" + c2 + "_color_img.txt";
			for (int i = 0; i < Vocabulary.COLORS.length; i++) {
				queryList.add(new SingleQueryThread(c1 + ","
						+ Vocabulary.COLORS[i], i % 3));
			}
			for (int i = 0; i < Vocabulary.COLORS.length; i++) {
				queryList.add(new SingleQueryThread(c2 + ","
						+ Vocabulary.COLORS[i], i % 3));
			}
		}

		// start multi-threading queries
		threadList = new ArrayList<Thread>();
		for (int i = 0; i < queryList.size(); i++) {
			Thread t = new Thread(queryList.get(i));
			threadList.add(t);
			t.start();
		}

		// make sure the querying threads are finished
		while (!this.isQueryFinished()) {
			;
		}

		// calculate the centered confidence
		this.calculateCenConf();

		// write the CenConf results in a text file
		try {
			PrintWriter writer = new PrintWriter(new File(cenConfFileName));

			int count = cenConf.length / 2;
			for (int i = 0; i < count; i++) {
				writer.println(cenConf[i] + " " + cenConf[i + count]);
			}
			writer.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		// write the images' url in two separate file
		try {
			PrintWriter c1writer = new PrintWriter(new File(c1UrlFileName));
			PrintWriter c2writer = new PrintWriter(new File(c2UrlFileName));

			int count = queryList.size() / 2;
			for (int i = 0; i < count; i++) {
				for (String c1url : queryList.get(i).getImgUrls()) {
					c1writer.print(c1url + "\t");
				}
				c1writer.print("\n");
				for (String c2url : queryList.get(i + count).getImgUrls()) {
					c2writer.print(c2url + "\t");
				}
				c2writer.print("\n");
			}

			c1writer.close();
			c2writer.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private boolean isQueryFinished() {
		int numOfAliveThreads = threadList.size();
		for (int i = 0; i < threadList.size(); i++) {
			if (!threadList.get(i).isAlive())
				numOfAliveThreads -= 1;
		}
		if (numOfAliveThreads == 0)
			return true;
		else
			return false;
	}

	private void calculateCenConf() {
		double totalNum = 0.0;
		double totalConcept1 = 0.0;
		double totalConcept2 = 0.0;
		int numOfTerms = queryList.size() / 2;
		int[] termsNum = new int[numOfTerms];
		for (int i = 0; i < queryList.size(); i++) {
			int currNum = queryList.get(i).getNumOfRes();
			totalNum += currNum;
			if (i < numOfTerms)
				totalConcept1 += currNum;
			else
				totalConcept2 += currNum;
		}

		for (int i = 0; i < numOfTerms; i++) {
			termsNum[i] = queryList.get(i).getNumOfRes()
					+ queryList.get(i + numOfTerms).getNumOfRes();
		}

		// calculate the CenConf
		cenConf = new double[queryList.size()];
		for (int i = 0; i < queryList.size(); i++) {
			if (i < numOfTerms) {
				cenConf[i] = (queryList.get(i).getNumOfRes() / totalConcept1)
						- (termsNum[i] / totalNum);
			} else {
				cenConf[i] = (queryList.get(i).getNumOfRes() / totalConcept2)
						- (termsNum[i - numOfTerms] / totalNum);
			}
		}
	}

	/**
	 * This method is used to replace the whitespace in a given string with
	 * underline "_"
	 * 
	 * @param orig
	 *            the original string
	 * @return string after transformation
	 */
	public static String transformString(String orig) {
		Pattern replace = Pattern.compile("\\s+");
		Matcher matcher2 = replace.matcher(orig);
		return matcher2.replaceAll("_");
	}

	public void displayCenConf() {
		for (int i = 0; i < cenConf.length; i++) {
			System.err.println(queryList.get(i).getQueryItem() + " : "
					+ cenConf[i]);
		}
	}
}
